/* 模块：random_access
 * 类型：适配器
 * 功能：通过具有 ::operator[] 以及 ::length() 函数的结构，对外提供一致的访问功能
 * 用法：
 * TODO======================================================================================
 */

#ifndef xpack_adapter_random_access
#define xpack_adapter_random_access
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::adapter_random_access::inc
#include"macro/xexport.hpp"
#include"macro/xitr_foreach.hpp"
#include"macro/xmodify.hpp"
#include"macro/xunlikely.hpp"
#include"math/index_system.hpp"
#include"meta/is_integer.hpp"
#include"meta/prop_type.hpp"
#pragma pop_macro("xuser")

namespace mixc::adapter_random_access {
    template<class final_t>
    concept can_random_access = requires(final_t seq, typename final_t::item_t item, uxx index, uxx length){
        item = seq.random_get(index);
        length = seq->length;
    };

    /* - base_t 为被此结构继承的结构类型，要求 base_t 具有以下函数
     *   item_t & base_t::operator[](uxx) const;
     *   uxx      base_t::length() const;
     * requires：
     * - base_t::item_t
     */
    template<class final_t, class item_t>
    xstruct(
        xtmpl(random_access, final_t, item_t)
    )
    public:
        /* 函数：下标随机访问（const 修饰）
         * 参数：
         * - index 为整数类型
         * 返回：
         * - 指定索引的元素的引用
         * 注意：
         * - 该函数支持回绕索引，即索引 -1 表示最后一个元素
         */
        template<class number_t>
        requires(
            inc::is_integer<inc::prop_type<number_t>>
        )
        decltype(auto) operator[] (number_t const & index) const {
            return this->access((inc::prop_type<number_t>)index);
        }

        xitr_foreach (item_t)
        xitr_foreachx(item_t)

    private:
        /* 函数：随机访问接口
         * 参数：
         * - index 为整数类型
         * 返回：
         * - 指定索引的元素的引用
         * 注意：
         * - 该函数支持回绕索引，即索引 -1 表示最后一个元素
         */
        template<inc::is_integer number_t>
        decltype(auto) access(number_t const & index) const {
            if constexpr (number_t(-1) > 0) {
                return xthex.random_get(uxx(index));
            }
            else {
                return xthex.random_get(index >= 0 ? uxx(index) : uxx(xthex->length + index));
            }
        }

        /* 函数：顺序访问模板
         * 参数：
         * - invoke 为元素访问回调，支持的签名如下
         *   void   invoke(item_t & value);
         *   void   invoke(item_t const & value);
         *   loop_t invoke(item_t & value);
         *   loop_t invoke(item_t const & value);
         *   void   invoke(uxx index, item_t & value);
         *   void   invoke(uxx index, item_t const & value);
         *   loop_t invoke(uxx index, item_t & value);
         *   loop_t invoke(uxx index, item_t const & value);
         * - itv 为访问区间
         */
        template<auto mode_v, class invoke_t, can_interval interval_t = co>
        void foreach_template(invoke_t const & invoke, interval_t const & itv = co{0, -1}) const {
            // 避免后续非法访问
            xunlikely(xthex->length == zero){
                return;
            }

            itv.normalize(xthex->length);

            uxx    l     = itv->left;
            uxx    r     = itv->right;
            uxx    step  = l <= r ? uxx(1) : uxx(-1);
            uxx    index = 0;

            for(;; l += step){
                if (auto & item = xthex.random_get(l); 
                    inc::itr_switch<mode_v>(xmodify(index), invoke, item) == loop_t::finish or l == r){
                    break;
                }
            }
        }
    $
}

#endif

xexport(mixc::adapter_random_access::random_access)
